package com.micro.core.frame.util;


import com.micro.common.util.SnowFlakeUtil;
import com.micro.core.handler.BaseContextHandler;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * <h2>实体默认赋值工具类</h2>
 * @author LevelCoder
 * @version V1.0.0
 * @email LevelCoder@126.com
 * @date 2020/5/19
 */
public class EntityUtil {

    /**
     * 系统默认主键id字段,如果为其他字段,则需传入id参数
     */
    private static final String DEFAULT_ID = "id";

    /**
     * 创建用户id
     */
    private static final String CREATE_USER_ID = "createUserId";

    /**
     * 创建时间
     */
    private static final String CREATE_TIME = "createTime";

    /**
     * 更新用户id
     */
    private static final String UPDATE_USER_ID = "updateUserId";

    /**
     * 更新时间
     */
    private static final String UPDATE_TIME = "updateTime";



    /**
     * 设置默认值:主键采用snow算法实现
     * @param entity
     * @param <T>
     */
    public static <T> void fillDefaultValues(T entity){
        if(ReflectionUtils.hasField(entity, "id")){
            ReflectionUtils.invokeSetter(entity, "id", SnowFlakeUtil.getId());
        }
    }

    /**
     * 拼接value值
     * @param entity
     * @param fields
     * @param <T>
     * @return
     */
    private static <T> Object[] assemble(T entity, String[] fields) {
        LinkedList value = new LinkedList();
        Field field;
        for(int i = 0 ; i < fields.length ; i++){
            if(ReflectionUtils.hasField(entity, fields[i])){
                switch (fields[i]){
                    case DEFAULT_ID:
                        value.add(SnowFlakeUtil.getId());
                        break;
                    case CREATE_USER_ID:
                        value.add(BaseContextHandler.getCustomerId());
                        break;
                    case CREATE_TIME:
                        field = ReflectionUtils.getAccessibleField(entity, CREATE_TIME);
                        if(field != null && field.getType().equals(Date.class)){
                            value.add(new Date());
                        }
                        break;
                    case UPDATE_USER_ID:
                        value.add(BaseContextHandler.getCustomerId());
                        break;
                    case UPDATE_TIME:
                        field = ReflectionUtils.getAccessibleField(entity, UPDATE_TIME);
                        if(field != null && field.getType().equals(Date.class)){
                            value.add(new Date());
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        return value.toArray();
    }

    /**
     * 通用注入创建/更新信息 用户信息通过放到session下进行存储/后续可以考虑放到缓存中或者内存中
     * @param entity         实体对象
     * @param requestType    true为新增/false为修改
     * @param <T>
     */
    public static <T> void assignment(T entity,boolean requestType){
        String[] fields = null;
        Object [] value = null;
        if(requestType){
            String[] defaultFields = {DEFAULT_ID,CREATE_USER_ID,CREATE_TIME};
            fields = validataFields(entity,defaultFields);
            value = assemble(entity,fields);
        }else{
            String[] defaultFields = {UPDATE_USER_ID,UPDATE_TIME};
            fields = validataFields(entity,defaultFields);
            value = assemble(entity,fields);
        }
        setDefaultValues(entity, fields, value);
    }

    /**
     * 验证默认字段是否存在
     * @param entity           实体对象
     * @param defaultFields    需要比对的字段
     * @param <T>
     * @return
     */
    private static <T> String[] validataFields(T entity, String[] defaultFields) {
        List fields = new ArrayList();
        for(int i = 0 ; i < defaultFields.length ; i++){
            if(ReflectionUtils.hasField(entity, defaultFields[i])){
                fields.add(defaultFields[i]);
            }
        }
        return (String[])fields.toArray(new String[0]);
    }


    /**
     * 默认赋值
     * @param entity
     * @param fields
     * @param value
     * @param <T>
     */
    private static <T> void setDefaultValues(T entity, String[] fields, Object[] value) {
        for(int i = 0; i < fields.length; i++){
            String field = fields[i];
            if(ReflectionUtils.hasField(entity, field)){
                ReflectionUtils.invokeSetter(entity, field, value[i]);
            }
        }
    }
}
